package com.smart.community.commons.utils;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.smart.community.commons.dto.FileInfoDTO;

import lombok.extern.slf4j.Slf4j;

/**
 * 文件信息工具类
 * 用于处理JSON格式的文件信息转换
 * 
 * @author Wu.Liang
 * @since 2025-01-30
 * @version 1.0.0
 * @updated 2025-01-30 - 修复LocalDateTime序列化问题，使用Spring配置的ObjectMapper
 */
@Slf4j
@Component
public class FileInfoUtils {
    
    // 使用Spring注入的ObjectMapper，确保与全局配置一致
    private static ObjectMapper objectMapper;
    
    @Autowired
    public void setObjectMapper(ObjectMapper objectMapper) {
        FileInfoUtils.objectMapper = objectMapper;
    }
    
    /**
     * 获取ObjectMapper实例
     * 
     * @return ObjectMapper实例
     */
    private static ObjectMapper getObjectMapper() {
        if (objectMapper == null) {
            // 如果Spring注入失败，创建默认配置的ObjectMapper
            objectMapper = new ObjectMapper();
            log.warn("Spring ObjectMapper注入失败，使用默认配置");
        }
        return objectMapper;
    }
    
    /**
     * 将文件信息列表转换为JSON字符串
     * 
     * @param fileInfoList 文件信息列表
     * @return JSON字符串
     */
    public static String toJsonString(List<FileInfoDTO> fileInfoList) {
        if (fileInfoList == null || fileInfoList.isEmpty()) {
            return null;
        }
        
        try {
            return getObjectMapper().writeValueAsString(fileInfoList);
        } catch (JsonProcessingException e) {
            log.error("转换文件信息列表为JSON字符串失败", e);
            return null;
        }
    }
    
    /**
     * 将JSON字符串转换为文件信息列表
     * 
     * @param jsonString JSON字符串
     * @return 文件信息列表
     */
    public static List<FileInfoDTO> fromJsonString(String jsonString) {
        if (StringUtils.isEmpty(jsonString)) {
            return new ArrayList<>();
        }
        
        try {
            return getObjectMapper().readValue(jsonString, new TypeReference<List<FileInfoDTO>>() {});
        } catch (JsonProcessingException e) {
            log.error("解析JSON字符串为文件信息列表失败: {}", jsonString, e);
            return Collections.emptyList();
        }
    }
    
    /**
     * 将单个文件URL转换为文件信息列表（兼容旧数据）
     * 
     * @param fileUrl 文件URL
     * @param uploadType 上传类型
     * @param uploadSource 上传来源
     * @return 文件信息列表
     */
    public static List<FileInfoDTO> fromSingleFileUrl(String fileUrl, String uploadType, String uploadSource) {
        List<FileInfoDTO> fileInfoList = new ArrayList<>();
        
        if (StringUtils.isNotEmpty(fileUrl)) {
            FileInfoDTO fileInfo = new FileInfoDTO();
            fileInfo.setId(generateFileId(uploadType));
            fileInfo.setFileName(extractFileNameFromUrl(fileUrl));
            fileInfo.setFileUrl(fileUrl);
            fileInfo.setFileSize(0L);
            fileInfo.setUploadType(uploadType);
            fileInfo.setUploadSource(uploadSource);
            fileInfo.setStatus("success");
            
            fileInfoList.add(fileInfo);
        }
        
        return fileInfoList;
    }
    
    /**
     * 从文件信息列表中获取第一个文件的URL（兼容旧数据）
     * 
     * @param fileInfoList 文件信息列表
     * @return 第一个文件的URL
     */
    public static String getFirstFileUrl(List<FileInfoDTO> fileInfoList) {
        if (fileInfoList != null && !fileInfoList.isEmpty()) {
            FileInfoDTO firstFile = fileInfoList.get(0);
            return firstFile.getFileUrl();
        }
        return null;
    }
    
    /**
     * 从JSON字符串中获取第一个文件的URL（兼容旧数据）
     * 
     * @param jsonString JSON字符串
     * @return 第一个文件的URL
     */
    public static String getFirstFileUrlFromJson(String jsonString) {
        List<FileInfoDTO> fileInfoList = fromJsonString(jsonString);
        return getFirstFileUrl(fileInfoList);
    }
    
    /**
     * 添加文件到JSON字符串
     * 
     * @param jsonString 现有JSON字符串
     * @param newFileInfo 新文件信息
     * @return 更新后的JSON字符串
     */
    public static String addFileToJson(String jsonString, FileInfoDTO newFileInfo) {
        List<FileInfoDTO> fileInfoList = fromJsonString(jsonString);
        fileInfoList.add(newFileInfo);
        return toJsonString(fileInfoList);
    }
    
    /**
     * 从JSON字符串中删除文件
     * 
     * @param jsonString 现有JSON字符串
     * @param fileId 要删除的文件ID
     * @return 更新后的JSON字符串
     */
    public static String removeFileFromJson(String jsonString, String fileId) {
        List<FileInfoDTO> fileInfoList = fromJsonString(jsonString);
        fileInfoList.removeIf(file -> fileId.equals(file.getId()));
        return toJsonString(fileInfoList);
    }
    
    /**
     * 更新JSON字符串中的文件
     * 
     * @param jsonString 现有JSON字符串
     * @param updatedFileInfo 更新的文件信息
     * @return 更新后的JSON字符串
     */
    public static String updateFileInJson(String jsonString, FileInfoDTO updatedFileInfo) {
        List<FileInfoDTO> fileInfoList = fromJsonString(jsonString);
        
        for (int i = 0; i < fileInfoList.size(); i++) {
            FileInfoDTO file = fileInfoList.get(i);
            if (updatedFileInfo.getId().equals(file.getId())) {
                fileInfoList.set(i, updatedFileInfo);
                break;
            }
        }
        
        return toJsonString(fileInfoList);
    }
    
    /**
     * 检查JSON字符串是否包含指定文件
     * 
     * @param jsonString JSON字符串
     * @param fileId 文件ID
     * @return 是否包含
     */
    public static boolean containsFile(String jsonString, String fileId) {
        List<FileInfoDTO> fileInfoList = fromJsonString(jsonString);
        return fileInfoList.stream().anyMatch(file -> fileId.equals(file.getId()));
    }
    
    /**
     * 获取JSON字符串中的文件数量
     * 
     * @param jsonString JSON字符串
     * @return 文件数量
     */
    public static int getFileCount(String jsonString) {
        List<FileInfoDTO> fileInfoList = fromJsonString(jsonString);
        return fileInfoList.size();
    }
    
    /**
     * 生成文件ID
     * 
     * @param uploadType 上传类型
     * @return 文件ID
     */
    private static String generateFileId(String uploadType) {
        return uploadType.toLowerCase() + "_" + System.currentTimeMillis();
    }
    
    /**
     * 从URL中提取文件名
     * 
     * @param fileUrl 文件URL
     * @return 文件名
     */
    private static String extractFileNameFromUrl(String fileUrl) {
        if (StringUtils.isEmpty(fileUrl)) {
            return "unknown_file";
        }
        
        int lastSlashIndex = fileUrl.lastIndexOf('/');
        if (lastSlashIndex >= 0 && lastSlashIndex < fileUrl.length() - 1) {
            return fileUrl.substring(lastSlashIndex + 1);
        }
        
        return fileUrl;
    }
    
    /**
     * 验证JSON字符串是否为有效的文件信息格式
     * 
     * @param jsonString JSON字符串
     * @return 是否有效
     */
    public static boolean isValidFileInfoJson(String jsonString) {
        if (StringUtils.isEmpty(jsonString)) {
            return true; // 空字符串认为是有效的
        }
        
        try {
            List<FileInfoDTO> fileInfoList = getObjectMapper().readValue(jsonString, new TypeReference<List<FileInfoDTO>>() {});
            return fileInfoList != null;
        } catch (JsonProcessingException e) {
            return false;
        }
    }
    
    /**
     * 格式化文件信息列表（用于日志输出）
     * 
     * @param fileInfoList 文件信息列表
     * @return 格式化字符串
     */
    public static String formatFileInfoList(List<FileInfoDTO> fileInfoList) {
        if (fileInfoList == null || fileInfoList.isEmpty()) {
            return "[]";
        }
        
        StringBuilder sb = new StringBuilder("[");
        for (int i = 0; i < fileInfoList.size(); i++) {
            FileInfoDTO file = fileInfoList.get(i);
            sb.append("{id:").append(file.getId())
              .append(",fileName:").append(file.getFileName())
              .append(",fileUrl:").append(file.getFileUrl())
              .append("}");
            
            if (i < fileInfoList.size() - 1) {
                sb.append(", ");
            }
        }
        sb.append("]");
        
        return sb.toString();
    }
    
    /**
     * 从文件信息列表创建实体列表
     * 
     * @param fileInfoList 文件信息列表
     * @param entityCreator 实体创建函数
     * @return 实体列表
     */
    public static <T> List<T> createEntityListFromFileInfoList(List<Map<String, Object>> fileInfoList, 
                                                               java.util.function.BiFunction<Map<String, Object>, Integer, T> entityCreator) {
        if (fileInfoList == null || fileInfoList.isEmpty()) {
            return new ArrayList<>();
        }
        
        List<T> entityList = new ArrayList<>();
        for (int i = 0; i < fileInfoList.size(); i++) {
            Map<String, Object> fileInfo = fileInfoList.get(i);
            if (fileInfo != null) {
                T entity = entityCreator.apply(fileInfo, i);
                if (entity != null) {
                    entityList.add(entity);
                }
            }
        }
        
        return entityList;
    }
    
    /**
     * 将实体列表转换为文件信息列表
     * 
     * @param entityList 实体列表
     * @param fileInfoExtractor 文件信息提取函数
     * @return 文件信息列表
     */
    public static <T> List<Map<String, Object>> convertEntityListToFileInfoList(List<T> entityList, 
                                                                                java.util.function.Function<T, Map<String, Object>> fileInfoExtractor) {
        if (entityList == null || entityList.isEmpty()) {
            return new ArrayList<>();
        }
        
        List<Map<String, Object>> fileInfoList = new ArrayList<>();
        for (T entity : entityList) {
            if (entity != null) {
                Map<String, Object> fileInfo = fileInfoExtractor.apply(entity);
                if (fileInfo != null) {
                    fileInfoList.add(fileInfo);
                }
            }
        }
        
        return fileInfoList;
    }
}
